#include "Scene.h"
#include <GameObject/Components.h>

namespace Engine2D
{
    Scene::Scene()
        : m_objectSize(0)
    {
    }

    std::shared_ptr<IObject> Scene::CreateBaseObject()
    {
        auto obj = std::make_shared<IObject>();
        obj->AddComponent<IDComponent>();
        obj->AddComponent<NameComponent>();
        obj->AddComponent<TagComponent>();
        obj->AddComponent<TransformComponent>();
        obj->AddComponent<RenderRectComponent>();
        AddObject(obj);
        return obj;
    }

    std::shared_ptr<IObject> Scene::CreateCareraObject()
    {
        auto obj = std::make_shared<IObject>();
        obj->AddComponent<IDComponent>();
        obj->AddComponent<NameComponent>("Camera");
        obj->AddComponent<TagComponent>("This is a camera");
        obj->AddComponent<TransformComponent>();
        obj->AddComponent<CameraComponent>();
        AddObject(obj);
        return obj;
    }

    void Scene::AddObject(std::shared_ptr<IObject> obj)
    {
        m_objects.push_back(obj);
        m_objectSize++;
    }

    bool Scene::RemoveObject(std::shared_ptr<IObject> obj)
    {
        for (auto && item : m_objects) {
            if (item == obj) {
                m_objects.erase(std::remove_if(m_objects.begin(), m_objects.end(), [obj](auto item) { return obj == item; }), m_objects.end());
                m_objectSize--;
                return true;
            }
            if (item->RemoveChild(obj)) {
                m_objectSize--;
                return true;
            }
        }
        return false;
    }

    bool Scene::RemoveObject(Uuid uuid)
    {
        return RemoveObject(GetObjectByUuid(uuid));
    }

    size_t Scene::Size()
    {
        return m_objectSize;
    }

    std::shared_ptr<IObject> Scene::GetObjectByUuid(Uuid uuid)
    {
        std::shared_ptr<IObject> out;
        this->Foreach<IDComponent>([&](std::shared_ptr<IObject> item) {
            if (item->GetComponent<IDComponent>().lock()->uuid == uuid) {
                out = item;
                return IObject::ForeachEnum::Break;
            }
            return IObject::ForeachEnum::Continue;
        });
        return out;
    }

    void Scene::Update()
    {
        for (auto && obj : m_objects) {
            obj->OnTick();
        }
    }

} // namespace Engine2D


